
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime, timezone
import threading
import time
import io
import json
import os
import tempfile
from typing import List
from urllib.parse import quote, unquote
import uuid
from django.conf import settings
from django.shortcuts import redirect
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from docx import Document
import openpyxl
import pandas as pd
import redis
import requests
from dingtalk_service.yida_client_base import YidaClientBase
from oss_service.views import bucket
import importlib
import logging
from reportservice.helpers import ApiResponse
from yida_app_service.utils.common_utils import acquire_lock, release_lock
from yida_app_service.utils.doc_utils import compare_code_in_pdf
from yida_app_service.utils.xmutils import convert_to_pdf
from yida_app_service.xu_cloud_client import XmCloudBaseClient
from django.core.cache import cache
from doc_service.utils import merge_pdfs_from_memory,download_file_bytes
from typing import List, Dict, Any

redis_client = redis.StrictRedis(host='10.8.0.83', port=6379, db=5)
logger = logging.getLogger(__name__)
admin_user_id = '014835331124251186'
def get_yida_client(company_name):
    """
    根据提供的模块名称动态导入YidaClient类。

    :param company_name: 模块名称，比如 'zhongcheng' 或 'shujian'
    :return: 导入的YidaClient类
    """
    module_name = f'yida_app_service.{company_name}.yida_config'
    module = importlib.import_module(module_name)
    return getattr(module, 'YidaClient')

def get_xm_client(company_name):
    """
    根据提供的模块名称动态导入XmCloudClient类。

    :param company_name: 模块名称，比如 'zhongcheng' 或 'shujian'
    :return: 导入的XmCloudClient类
    """
    module_name = f'yida_app_service.{company_name}.xm_cloud_config'
    module = importlib.import_module(module_name)
    return getattr(module, 'XmCloudClient')

@csrf_exempt
@require_http_methods(["GET"])
def download_file(request,url):
    if not bucket.object_exists(url):
        objs = bucket.list_objects(prefix=url)
        if objs.object_list:
            url = objs.object_list[0].key
        else:
            return ApiResponse.fail("文件不存在,请联系管理员")
    redirect_url = bucket.sign_url("GET",url,600)
    return redirect(redirect_url)

@csrf_exempt
@require_http_methods(["POST"])
def reset_serial_number(request,company_name):
    req_body = json.loads(request.body)
    form_uuid = req_body.get('form_uuid')
    form_inst_id = req_body.get('form_inst_id')
    update_data = req_body.get('update_data')
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    res = yida_client.update_form_data_by_id(form_uuid,admin_user_id,form_inst_id,update_data)
    if res == "success":
        return ApiResponse.success(message="更新成功")
    else:
        return ApiResponse.fail(message="更新失败")


@csrf_exempt
@require_http_methods(["POST"])
def gen_serial_number_v2(request,company_name):
    print("请求开始>>>>>>>")
    req_body = json.loads(request.body)
    form_uuid = req_body.get('form_uuid')
    form_inst_id = req_body.get('form_inst_id')
    code_type = req_body.get('code_type',"")
    sn_code = req_body.get('sn_code') # 流水号前缀
    sn_code_field = req_body.get('sn_code_field') # 编号字段id
    zfill = req_body.get('zfill',5)
    update_sn = req_body.get('update_sn',True) # 是否自动修改流水号
    match_params = req_body.get('match_params',{ # 匹配参数
        sn_code_field: sn_code
    })
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    sn_cache_key = f"{company_name}:sn_code{code_type}:{sn_code}"
    # 加锁
    lock_key = f"{sn_cache_key}_lock"
    lock_acquired = acquire_lock(lock_key)
    # 如果没有获取到锁，则等待一段时间并重试
    while not lock_acquired:
        time.sleep(1)  # 等待 1000 毫秒
        lock_acquired = acquire_lock(lock_key)
    current_value = cache.get(sn_cache_key)
    if not current_value:
        current_value = 0
        retry_count = 5
        while retry_count > 0:
            try:
                result = yida_client.get_form_data_by_search_field(form_uuid,
                                                          admin_user_id,
                                                          match_params,
                                                          page_size=10,
                                                          dynamic_order={sn_code_field:"-"})
                if result == None:
                    retry_count -= 1
                else:
                    break
            except Exception as err:
                logger.error(f"Error occurred while fetching data: {err}")
                retry_count -= 1
        for res_item in result:
            form_data = res_item.form_data
            old_code = form_data.get(sn_code_field)
            if old_code and old_code.startswith(sn_code) and res_item.form_instance_id != form_inst_id:
                try:
                    # if "-" in old_code:
                    #     old_code = old_code.split("-")[0]
                    increment_id = int(old_code.replace(sn_code,""))
                except ValueError as err:
                    increment_id = 0
                if increment_id > current_value:
                    current_value = increment_id
        cache.set(sn_cache_key, current_value, None)
    current_value += 1
    full_code = f"{sn_code}{str(current_value).zfill(int(zfill))}"
    if not form_inst_id:
        release_lock(lock_key)
        return ApiResponse.success(full_code)
    if update_sn:
        threading.Thread(target=update_yida_sn, args=(yida_client,
                                                      sn_cache_key,
                                                      lock_key,
                                                      form_uuid,
                                                      admin_user_id,
                                                      form_inst_id,
                                                      {
                                                        sn_code_field: full_code
                                                      })).start()
    else:
        try:
            cache.incr(sn_cache_key, 1)
        finally:
            release_lock(lock_key)
    return ApiResponse.success(full_code)

@csrf_exempt
@require_http_methods(["GET"])
def current_serial_number_v2(request,company_name):
    sn_code = request.GET.get("sn_code")
    code_type = request.GET.get("code_type","")
    sn_cache_key = f"{company_name}:sn_code{code_type}:{sn_code}"
    current_value = cache.get(sn_cache_key,0)
    return ApiResponse.success(current_value+1)



@csrf_exempt
@require_http_methods(["POST"])
def reset_serial_number_v2(request,company_name):
    req_body = json.loads(request.body)
    zfill = int(req_body.get('zfill',5))
    full_code = req_body.get('full_code')
    code_type = req_body.get("code_type","")
    sn_code = full_code[:-zfill]
    sn_cache_key = f"{company_name}:sn_code{code_type}:{sn_code}"
    cache.delete(sn_cache_key)
    return ApiResponse.success("序列号重置成功")

def update_yida_sn(yida_client:YidaClientBase,sn_cache_key,lock_key,form_uuid,user_id,form_inst_id,update_field) -> str:
    try:
        res = yida_client.update_form_data_by_id(form_uuid,
                                                 user_id,
                                                 form_inst_id,
                                                 update_field)
        if res == "success":
            cache.incr(sn_cache_key, 1)
    finally:
        release_lock(lock_key)
@csrf_exempt
@require_http_methods(["POST"])
def gen_serial_number(request,company_name):
    retry_count = 10
    try:
        YidaClient = get_yida_client(company_name)
        yida_client:YidaClientBase = YidaClient()
        req_body = json.loads(request.body)
        form_uuid = req_body.get('form_uuid')
        match_field_data = req_body.get('match_field')
        sn_field = req_body.get('sn_field')
        while retry_count > 0:
            try:
                if isinstance(match_field_data,list):
                    match_field_data = match_field_data + [{"key":sn_field,"value":"","type":"DOUBLE","operator":"is_not","componentName":"NumberField"}]
                result = yida_client.get_form_data_by_search_field(form_uuid=form_uuid,
                                                          userId=admin_user_id,
                                                          search_field=match_field_data,
                                                          page_size=5,
                                                          dynamic_order={sn_field:"-"})
                if result:
                    serial_number = result[0].form_data.get(sn_field,0)+1
                    return ApiResponse.success(serial_number)
                elif len(result) == 0:
                    return ApiResponse.success(data=1,message="未找到以往编号，重新生成编号")
            except Exception as err:
                logger.error("宜搭查询错误，请重试",err)
                retry_count -= 1
                time.sleep(1)
        return ApiResponse.fail(message="获取流水号超时")
    except Exception as err:
        logger.error(err)
        return ApiResponse.fail("获取序列号失败")
    

@csrf_exempt
@require_http_methods(["POST"])
def gen_docx_by_model(request,company_name,model_id):
    req_data = json.loads(request.body)
    render_data = req_data.get("render_data")
    form_uuid = req_data.get("form_uuid")
    form_inst_id = req_data.get("form_inst_id")
    attachment_key = req_data.get("attachment_info")
    XmCloudClient = get_xm_client(company_name)
    xm_client:XmCloudBaseClient = XmCloudClient()
    result = xm_client.render_model(model_id,render_data=render_data)
    if(result.get("code") == 200):
        res_data = result.get("data")
        if form_uuid:
            YidaClient = get_yida_client(company_name)
            yida_client:YidaClientBase = YidaClient()
            now_date = datetime.now(timezone.utc)
            yida_client.update_form_data_by_id(form_uuid,admin_user_id,form_inst_id,{
                attachment_key:[
                    {
                      "downloadUrl": res_data.get("download_url"),
                      "name": f"附件_{now_date.strftime('%Y%m')}.pdf",
                      "previewUrl": res_data.get("preview_url"),
                      "url": res_data.get("download_url"),
                      "ext": "pdf"
                    }
                ]
            })
        else:
            return ApiResponse.success(data=res_data)
    return ApiResponse.fail(message="文档生成失败")
    
        

@csrf_exempt
@require_http_methods(["POST"])
def gen_report_xlsx(request,company_name,model_id):
    try:
        data = json.loads(request.body)
        render_data = data.get("render_data")
        attachment_info = data.get("attachment_info")
        XmCloudClient = get_xm_client(company_name)
        xm_client:XmCloudBaseClient = XmCloudClient()
        result = xm_client.render_model_xlsx(model_id,render_data)
        if result.get("code") == 200:
            res_data = result.get("data")
        else:
            return ApiResponse.fail(message="参数错误")
    except Exception as err:
        logger.error(err)
        return ApiResponse.fail(message="报告生成失败")
    if res_data.get("id"):
        result = xm_client.gen_detection_record_url(res_data.get("id"))
        if result.get("code") != 200:
            return ApiResponse.fail(message="未找到报告生成记录")
        res = result.get("data")
        YidaClient = get_yida_client(company_name)
        yida_client:YidaClientBase = YidaClient()
        form_uuid = attachment_info.get('form_uuid')
        form_inst_id = attachment_info.get('form_inst_id')
        component_id = attachment_info.get('component_id')
        now_date = datetime.now(timezone.utc)
        yida_client.update_form_data_by_id(form_uuid,admin_user_id,form_inst_id,{
        component_id:[
                {
                  "downloadUrl": res["output_url"],
                  "name": f"报告附件_{now_date.strftime('%Y%m')}.pdf",
                  "previewUrl": res["preview_url"],
                  "url": res["download_url"],
                  "ext": "pdf"
                }
              ]
        })
        return ApiResponse.success(message="更新成功")
    else:
        return ApiResponse.fail(message="报告参数错误")


@csrf_exempt
@require_http_methods(["GET"])
def update_report_attachment(request,company_name):
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    form_uuid = request.GET.get('form_uuid')
    form_inst_id = request.GET.get('form_inst_id')
    component_id = request.GET.get('component_id')
    access_token = request.GET.get('access_token')
    render_id = request.GET.get('render_id')
    api_url = f"https://api.zjcxjc.cn/api/v1/xu-cloud/detection-model-render-record/{render_id}/gen-url/?file_type=input"
    headers = {
        'Authorization': f'Token {access_token}'
    }
    response = requests.get(api_url,headers=headers)
    if response.status_code == 200:
        res = response.json()
        yida_client.update_form_data_by_id(form_uuid,admin_user_id,form_inst_id,{
            component_id:[
                {
                  "downloadUrl": res["data"],
                  "name": "render_20240404.xlsx",
                  "previewUrl": res["data"],
                  "url": res["data"],
                  "ext": "xlsx"
                }
              ]
        })
        return ApiResponse.success(message="更新成功")

@csrf_exempt
@require_http_methods(["POST"])
def create_detection_model(request,company_name):
    model_info = json.loads(request.body)
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    XmCloudClient = get_xm_client(company_name)
    xm_client:XmCloudBaseClient = XmCloudClient()
    result = xm_client.create_model(model_info=model_info)
    if result.get("code") != 200:
        return ApiResponse.fail(message="报告参数错误")
    else:
        res_data = result.get("data")
        form_uuid = model_info.get("form_uuid")
        component_id = model_info.get("component_id")
        form_inst_id = model_info.get("form_inst_id")
        res = yida_client.update_form_data_by_id(form_uuid,admin_user_id,form_inst_id,{
            component_id:res_data.get("id")
        })
        if res == "success":
            return ApiResponse.success(message="模版创建成功")
        else:
            return ApiResponse.fail(message="更新失败")

@csrf_exempt
@require_http_methods(["GET"])
def load_original_record(request,company_name):
    download_url = unquote(request.GET.get('download_url'))
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    full_download_url = yida_client.get_full_download_url(
        user_id=admin_user_id, download_url=download_url)

    url = full_download_url.body.result  # 从完整的下载链接响应中提取实际的文件下载链接。
    with requests.Session() as session:  # 使用 requests 库创建一个会话对象，用于发送 HTTP 请求。
        response = session.get(url)  # 发送 GET 请求以获取文件内容。
        if response.status_code == 200:
            file_content = response.content
            file_stream = io.BytesIO(file_content)
            # 使用 openpyxl 打开内存中的 Excel 文件
            workbook = openpyxl.load_workbook(file_stream)
            sheet = workbook["钢材原材料力学工艺性能检测原始记录"]
            cell = sheet["B5"]
            res_data = {
                "textField_lvhscxaz":cell.value
            }
            return ApiResponse.success(data=res_data)
        

@csrf_exempt
@require_http_methods(["POST"])
def attachment_to_xmoffice(request,company_name):
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    req_data = json.loads(request.body)
    form_uuid = req_data.get('form_uuid')
    form_inst_id = req_data.get('form_inst_id')
    component_id = req_data.get('component_id')
    yida_instance = yida_client.get_form_items_by_ids(form_uuid,form_inst_id,admin_user_id)
    attachments = yida_instance[0].form_data.get(component_id)
    if attachments:
        attachments_info = json.loads(attachments)
        download_url = attachments_info[0].get("downloadUrl")
        full_download_url = yida_client.get_full_download_url(admin_user_id,download_url)
        url = full_download_url.body.result  # 从完整的下载链接响应中提取实际的文件下载链接。
        with requests.Session() as session:  # 使用 requests 库创建一个会话对象，用于发送 HTTP 请求。
            response = session.get(url)  # 发送 GET 请求以获取文件内容。
            if response.status_code == 200:
                file_info = attachments_info[0]
                file_content = response.content
                temp_dir = tempfile.mkdtemp()
                temp_file_path = os.path.join(temp_dir, file_info['name'])
                print(f"文件已存入缓存文件：{temp_file_path}")
                with open(temp_file_path, 'wb') as temp_file:
                    temp_file.write(file_content)
                oss_key = f"yida-app/{company_name}/{form_uuid}/{form_inst_id}/{component_id}/{file_info['name']}"
                pdf_file_name = "".join(file_info['name'].split(".")[:-1] + [".pdf"])
                oss_pdf_key = f"yida-app/{company_name}/{form_uuid}/{form_inst_id}/{component_id}/{pdf_file_name}"
                convert_to_pdf(temp_file_path,temp_dir)
                bucket.put_object_from_file(oss_key,temp_file_path)
                pdf_path = os.path.join(temp_dir, pdf_file_name)
                bucket.put_object_from_file(oss_pdf_key,pdf_path)
                XmCloudClient = get_xm_client(company_name)
                xm_client:XmCloudBaseClient = XmCloudClient()
                suffix = file_info['name'].split(".")[-1]
                res = xm_client.post_office_file({
                    "name":file_info['name'],
                    "uid":f"yida-upload-{datetime.now().timestamp()}",
                    "size":file_info["size"],
                    "suffix":suffix,
                    "path":oss_key
                })
                if res.get("code") == 200:
                    wopi_key = res.get("data").get("id")
                    base_url = "https://office.zjxmyq.cn/browser/2414408576/cool.html?lang=zh-CN&WOPISrc="
                    preview_wopi_url = f"https://api.zjcxjc.cn/api/v1/xu-cloud/wopi/files/{wopi_key}?access_token={xm_client.xm_token[6:]}&file_type=input"
                    preview_url = base_url+quote(preview_wopi_url)
                    out_url = f"https://api.zjcxjc.cn/api/v1/yida-app/common/download_file/{oss_pdf_key}"
                    yida_client.update_form_data_by_id(form_uuid,admin_user_id,form_inst_id,{
                        component_id:[{
                            "downloadUrl": out_url,
                            "name": file_info["name"],
                            "previewUrl": preview_url,
                            "url": preview_url,
                            "ext": "docx"
                        }]
                    })
                    return ApiResponse.success([{
                            "downloadUrl": out_url,
                            "name": file_info["name"],
                            "previewUrl": preview_url,
                            "url": preview_url,
                            "ext": "docx"
                        }])
                

@csrf_exempt
@require_http_methods(["GET"])
def print_form_data(request,company_name,model_id):
    form_uuid = request.GET.get('form_uuid')
    form_instance_id = request.GET.get('form_instance_id')
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    result = yida_client.get_form_items_by_ids(form_uuid=form_uuid,form_inst_id=form_instance_id,userId=admin_user_id)
    if result:
        XmCloudClient = get_xm_client(company_name)
        render_data = result[0].form_data
        xm_client:XmCloudBaseClient = XmCloudClient()
        result = xm_client.render_model(model_id,render_data=render_data)
        if(result.get("code") == 200):
            res_data = result.get("data")
            return redirect(res_data.get("download_url"))
    return ApiResponse.fail("参数错误")


@csrf_exempt
@require_http_methods(["GET"])
def gen_form_data_pdf_by_model(request,company_name,model_id):
    form_uuid = request.GET.get('form_uuid')
    form_instance_id = request.GET.get('form_instance_id')
    component_id = request.GET.get('component_id')
    model_type = request.GET.get('model_type',"docx")
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    result = yida_client.get_form_items_by_ids(form_uuid=form_uuid,form_inst_id=form_instance_id,userId=admin_user_id)
    if result:
        XmCloudClient = get_xm_client(company_name)
        render_data = result[0].form_data
        render_data["current_date"] = int(datetime.now().timestamp() * 1000)
        xm_client:XmCloudBaseClient = XmCloudClient()
        if model_type == "docx":
            result = xm_client.render_model(model_id,render_data=render_data)
        elif model_type == "xlsx":
            result = xm_client.render_model_xlsx(model_id,render_data=render_data)
        if(result.get("code") == 200):
            res_data = result.get("data")
            yida_client.update_form_data_by_id(form_uuid,admin_user_id,form_instance_id,{
                component_id:[{
                                "downloadUrl": res_data.get("download_url"),
                                "name": f"{form_uuid}_{form_instance_id}.pdf",
                                "previewUrl": res_data.get("download_url"),
                                "url": res_data.get("download_url"),
                                "ext": "pdf"
                            }]
            })
            return ApiResponse.success(res_data.get("download_url"))
        else:
            return ApiResponse.fail(result.get("message"))
        

@csrf_exempt
@require_http_methods(["GET"])
def upload_price_shell(request,company_name):
    # 从 GET 请求参数中获取下载链接，并解码该链接。unquote 用于处理 URL 编码。
    download_url = unquote(request.GET.get('download_url'))
    form_inst_id = request.GET.get('form_inst_id')
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    full_download_url = yida_client.get_full_download_url(
        user_id=admin_user_id, download_url=download_url)
    url = full_download_url.body.result  # 从完整的下载链接响应中提取实际的文件下载链接。
    with requests.Session() as session:  # 使用 requests 库创建一个会话对象，用于发送 HTTP 请求。
        response = session.get(url)  # 发送 GET 请求以获取文件内容。
        if response.status_code == 200:
            file_content = response.content  # 从响应中获取文件的内容。
            bucket.put_object(
                rf"yida-app/{company_name}/price_sheet/{form_inst_id}.xlsx", file_content)
            return ApiResponse.success()
    return ApiResponse.fail("清单上传失败")


@csrf_exempt
@require_http_methods(["GET"])
def prepare_price_shell(request,company_name):
    form_inst_id = request.GET.get('form_inst_id')
    form_uuid = request.GET.get('form_uuid')
    attachement_id = request.GET.get('attachement_id')
    redis_client = cache.client.get_client()
    cursor, keys = redis_client.scan(match=f"{settings.CACHES_PREFIX}:{company_name}:{form_inst_id}:*",count=1)
    if keys:
        return ApiResponse.success("success")
    YidaClient = get_yida_client(company_name)
    yida_client: YidaClientBase = YidaClient()
    result = yida_client.get_form_items_by_ids(form_uuid,form_inst_id,admin_user_id)
    if result:
        price_shell_attachement = json.loads(result[0].form_data.get(attachement_id))
        full_url = yida_client.get_full_download_url(admin_user_id,price_shell_attachement[0].get("downloadUrl"))
        excel_file = download_file_bytes(full_url.body.result)
        df = pd.read_excel(excel_file)
        for index, row in df.iterrows():
            redis_key = f"{str(row['检测项目'])}-{str(row['检测参数'])}"
            redis_value = str(row['费用'])
            # 存储到Redis
            cache.set(f"{company_name}:{form_inst_id}:{redis_key}", redis_value,3600)
        return ApiResponse.success("success")
    else:
        return ApiResponse.fail("未找到价格清单")
    
@csrf_exempt
@require_http_methods(["GET"])
def get_single_price(request,company_name):
    form_inst_id = request.GET.get('form_inst_id')
    param_name = request.GET.get('param_name')
    param_key = rf"{company_name}:{form_inst_id}:{param_name}"
    price = cache.get(param_key)
    if price:
        return ApiResponse.success(float(price))
    else:
        return ApiResponse.fail("未找到价格")
            


@csrf_exempt
@require_http_methods(["POST"])
def batch_print_yida_file(request, company_name):
    YidaClient = get_yida_client(company_name)
    yida_client: YidaClientBase = YidaClient()
    req_data = json.loads(request.body)
    form_uuid = req_data.get('form_uuid')
    form_inst_id_list = req_data.get('form_inst_id_list', [])
    file_component_id = req_data.get('file_component_id')

    if form_uuid and form_inst_id_list and file_component_id:
        reports_pdf_files = []
        futures = {}
        executor = ThreadPoolExecutor()
        try:
            for form_inst_id in form_inst_id_list:
                    yida_instance = yida_client.get_form_items_by_ids(form_uuid, form_inst_id, admin_user_id)
                    form_data = yida_instance[0].form_data
                    yida_file_url: str = json.loads(form_data[file_component_id])[0].get("downloadUrl")
                    is_myself_file = "zjxmyq" in yida_file_url
                    if not is_myself_file:
                        full_download_url = yida_client.get_full_download_url(admin_user_id, yida_file_url)
                        futures[form_inst_id] = executor.submit(download_file_bytes, full_download_url.body.result)
                    else:
                        futures[form_inst_id] = executor.submit(download_file_bytes, yida_file_url)

            for form_inst_id in form_inst_id_list:
                try:
                    reports_pdf_files.append(futures[form_inst_id].result())
                except Exception as e:
                    logger.error(f"下载任务失败: {e}")

            output = io.BytesIO()
            merge_pdfs_from_memory(reports_pdf_files, output)
            output.seek(0)
            output_file = io.BytesIO(output.getvalue())

            oss_pdf_key = f"yida-app/{company_name}/{form_uuid}/报告{uuid.uuid4()}.pdf"
            bucket.put_object(oss_pdf_key, output_file)
            out_url = f"https://api.zjcxjc.cn/api/v1/yida-app/common/download_file/{oss_pdf_key}"
            return ApiResponse.success(data=out_url, message='报告打印成功')
        finally:
            executor.shutdown(wait=True)  # 显式关闭线程池
            for file in reports_pdf_files:
                file.close()

    return ApiResponse.fail('报告打印失败')



@csrf_exempt
@require_http_methods(["POST"])
def batch_print(request, company_name):
    YidaClient = get_yida_client(company_name)
    yida_client: YidaClientBase = YidaClient()
    req_data = json.loads(request.body)
    form_uuid = req_data.get('form_uuid')
    form_inst_id_list: List[str] = req_data.get('form_inst_id_list', [])
    model_id = req_data.get('model_id')

    info_data:List[object] = req_data.get('info_data',[])
    table_data:List[object] = req_data.get('table_data',[])

    if form_uuid and form_inst_id_list and model_id and table_data:
        render_data ={}
        if info_data:
            info_data_value = get_info_data_from_yida(yida_client,form_uuid,form_inst_id_list[0],info_data,admin_user_id)
            render_data = {**info_data_value}
        data = []
        for form_inst_id in form_inst_id_list:
            table_data_value = get_info_data_from_yida(yida_client,form_uuid,form_inst_id,table_data,admin_user_id)
            data.append(table_data_value)
        render_data["table_data"] = data
        render_data["打印时间"]=datetime.now().timestamp()
        XmCloudClient = get_xm_client(company_name)
        xm_client:XmCloudBaseClient = XmCloudClient()
        result_render = xm_client.render_model_xlsx(model_id,render_data)
        if result_render.get("code") == 200:
            res_data = result_render.get("data")
            result_url =xm_client.gen_detection_record_url(res_data.get("id"))
            if result_url.get("code") == 200:
                res = result_url.get("data")
                return ApiResponse.success(res.get("preview_url"))
        return ApiResponse.fail("报告打印失败")      

def get_info_data_from_yida(yida_client, form_uuid, form_inst_id, info_data: List[object], admin_user_id) -> Dict[str, Any]:
    # 获取表单实例数据
    yida_instance = yida_client.get_form_items_by_ids(form_uuid, form_inst_id, admin_user_id)
    form_data = yida_instance[0].form_data
    info_data_value = {}

    def process_field(field, current_form_data):
        # 处理没有子字段的情况
        if not field.get("fields") and field["name"]:
            
            # 单行文本组件
            if  field["name"].startswith("textField") or field["name"].startswith("textareaField"):
                info_data_value[field["name"]] = current_form_data.get(field["name"])
            # 成员组件
            elif field["name"].startswith("employeeField"):
                # 获取人员信息，可能包含多个人
                persons = current_form_data.get(field["name"], [])
                if field.get("isMultiple", False):
                    # 如果是多人字段，将名字用顿号分隔
                    info_data_value[field["name"]] = "、".join(persons)
                else:
                    # 如果不是多人字段，只取第一个员工的名字
                    info_data_value[field["name"]] = persons[0] if persons else None
            # elif field["name"].startswith("dateField"):
                # 获取时间信息,如果
        # 处理有子字段的情况
        else:
            # 如果字段名以"associationFormField"开头
            if field["name"].startswith("associationFormField"):
                association_form_str = field["name"] + "_id"
                # 获取关联表单的ID
                association_form_id = current_form_data.get(association_form_str)
                if association_form_id:
                    # 获取关联表单的数据
                    association_form_data = yida_client.get_associated_form_data(association_form_id, admin_user_id)
                    if association_form_data:
                        # 递归处理每个子字段
                        for sub_field in field["fields"]:
                            process_field(sub_field, association_form_data)

    # 遍历info_data中的每个字段并进行处理
    for field in info_data:
        process_field(field, form_data)

    return info_data_value

# -------------------------------------------------------------------->

@csrf_exempt
@require_http_methods(['GET'])
# @description:获取协会证书数据
# @author:熊吕军
# @params:{   
#   company_name <str:company_name>    公司名称对应文件 zhongji  nanxing  ..... 
#   
#   form_uuid   表单id
# }

def get_associate_certificate_info(request, company_name):
    form_uuid = request.GET.get('form_uuid')
    # 导入yida模块
    YidaClient = get_yida_client(company_name)

    # 接口请求数据
    def get_data_from_api(id_no):
        api_url="https://api.zjcxjc.cn/api/v1/association/get_cetificate_infos_by_id"
        try:           
            response = requests.get(api_url, params={
                "id_no":id_no
            })
            if response.status_code == 200:
                res_data = response.json()
                print(res_data)
                return res_data["data"]
            else:
                raise ValueError("协会接口请求失败")
        except requests.RequestException as e:
            raise ValueError("协会接口请求失败")
            
    try:
        yida_client:YidaClientBase = YidaClient()
        # 获取所有表单数据
        instances,total=yida_client.get_all_form_data_by_search_field(
            form_uuid=form_uuid,
            userId=admin_user_id,
            search_field=[]
        )
        id_no_list=[instance.form_data["textField_ltcc4gg8"] for instance in instances]
        id_map={instance.form_data["textField_ltcc4gg8"]: instance.form_instance_id for instance in instances}
        print(id_map)
        # print(id_no_list)

        err_list=[]
        for id_no in id_no_list:
            try:
                res_data=get_data_from_api(id_no)
                form_instance_id=id_map[res_data["id_no"]]
                has_cert_text="是" if res_data["has"] else "否"
                # print(form_instance_id)
                yida_client.update_form_data_by_id(
                    form_uuid=None,
                    userId=admin_user_id,
                    form_inst_id=form_instance_id,
                    update_field={
                        "tableField_lolhb68u":res_data["child_table"],
                        "selectField_m0q1ewu2":has_cert_text,
                        "attachmentField_ltcc4ggj":res_data["cert_url"]
                    }
                )
            except:
                err_list.append(id_no)
                continue
            

        return ApiResponse.success(message="合格证调用成功,data为失败人员",data=err_list)        
    except Exception as e:
        return ApiResponse.fail(message=e)


@csrf_exempt
@require_http_methods(['POST'])
def copy_form_data(request, company_name):
    req_data = json.loads(request.body)
    form_uuid = req_data.get('form_uuid')
    form_inst_id = req_data.get('form_inst_id')
    count_component_id = req_data.get('count_component_id')
    sn_code_component_id = req_data.get('sn_code_component_id',[])
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    result = yida_client.get_form_items_by_ids(form_uuid=form_uuid,
                                      form_inst_id=form_inst_id,
                                      userId=yida_client.admin_user_id)
    form_data = result[0].form_data
    creator = result[0].creator_user_id
    count = form_data.get(count_component_id)
    for i in range(int(count)-1):
        new_form_data = {}
        for key in form_data:
            if key == count_component_id:
                new_form_data[key] = 1
            elif key in sn_code_component_id:
                new_form_data[key] = ""
            elif key.startswith("associationFormField"):
                asso_key = key[:-3]
                asso_val = json.loads(json.loads(form_data[key]))
                new_form_data[asso_key] = asso_val
            elif key.endswith("_id"):
                continue
            elif key.startswith("selectField"):
                new_form_data[key] = form_data[key+"_id"]
            elif key.startswith("checkboxField"):
                new_form_data[key] = form_data[key+"_id"]
            elif key.startswith("radioField"):
                new_form_data[key] = form_data[key+"_id"]
            elif key.startswith("multiSelectField"):
                new_form_data[key] = form_data[key+"_id"]
            elif key.startswith("employeeField"):
                new_form_data[key] = form_data[key+"_id"]
            else:
                new_form_data[key] = form_data[key]
        result = yida_client.create_form_data(form_uuid=form_uuid,
                                     userId=creator,
                                     formDataJson=new_form_data)
    return ApiResponse.success("复制成功")


@csrf_exempt
@require_http_methods(['POST'])
def copy_process_data(request, company_name):
    req_data = json.loads(request.body)
    form_uuid = req_data.get('form_uuid')
    process_code = req_data.get('process_code')
    form_inst_id = req_data.get('form_inst_id')
    count_component_id = req_data.get('count_component_id')
    sn_code_component_id = req_data.get('sn_code_component_id',[])
    sn_code = req_data.get('sn_code',"")
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    result = yida_client.get_form_items_by_ids(form_uuid=form_uuid,
                                      form_inst_id=form_inst_id,
                                      userId=yida_client.admin_user_id)
    form_data = result[0].form_data
    creator = result[0].creator_user_id
    count = form_data.get(count_component_id)
    for i in range(int(count)-1):
        new_form_data = {}
        for key in form_data:
            if key == count_component_id:
                new_form_data[key] = 1
            elif key in sn_code_component_id:
                new_form_data[key] = sn_code
            elif key.startswith("associationFormField"):
                asso_key = key[:-3]
                asso_val = json.loads(json.loads(form_data[key]))
                new_form_data[asso_key] = asso_val
            elif key.endswith("_id"):
                continue
            elif key.startswith("selectField"):
                new_form_data[key] = form_data[key+"_id"]
            elif key.startswith("checkboxField"):
                new_form_data[key] = form_data[key+"_id"]
            elif key.startswith("radioField"):
                new_form_data[key] = form_data[key+"_id"]
            elif key.startswith("multiSelectField"):
                new_form_data[key] = form_data[key+"_id"]
            elif key.startswith("employeeField"):
                new_form_data[key] = form_data[key+"_id"]
            else:
                new_form_data[key] = form_data[key]
        result = yida_client.create_process_instance(form_uuid=form_uuid,
                                     userId=creator,
                                     formDataJson=new_form_data,
                                     process_code=process_code)
    return ApiResponse.success("复制成功")
    

@csrf_exempt
@require_http_methods(['POST'])
def cache_form_data(request, company_name):
    req_data = json.loads(request.body)
    form_uuid = req_data.get("form_uuid")
    search_data = req_data.get("search_data")
    pk = req_data.get("pk")
    key = f"xu_yida:{company_name}:form_data:{form_uuid}:{pk}"
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    result = yida_client.get_form_data_by_search_field(form_uuid,yida_client.admin_user_id,search_data)
    if result:
        financial_process = yida_client.get_approve_history(
            result[0].form_instance_id,
            admin_user_id
        )
        process_status = "未知"
        for financial_process_item in financial_process:
            if financial_process_item.type == 'TODO':
                process_status = financial_process_item.show_name
                break
        cache_data = {
            "form_data": result[0].form_data,
            "form_instance_id":result[0].form_instance_id,
            "process_status":process_status,
        }
        value = json.dumps(cache_data,skipkeys=True)
        redis_client.set(key,value,ex=None)
        return ApiResponse.success(data=value)


@csrf_exempt
@require_http_methods(["GET"])
def compare_code_in_doc(request,company_name):
    '''比对编号'''
    downloadUrl = request.GET.get("downloadUrl")
    name = request.GET.get("name")
    ext = name.split(".")[-1]
    if not downloadUrl:
        return ApiResponse.fail(message="下载链接获取失败")
    report_code: str = request.GET.get("code")
    admin_user_id = "301546025724261514"
    YidaClient = get_yida_client(company_name)
    yida_client:YidaClientBase = YidaClient()
    full_download_url = yida_client.get_full_download_url(
        user_id=admin_user_id, download_url=downloadUrl)
    response = requests.get(full_download_url.body.result)
    if response.status_code == 200:
        pdf_content = io.BytesIO(response.content)
        try:
            if ext == "pdf":
                if compare_code_in_pdf(pdf_content=pdf_content,code=report_code):
                    return ApiResponse.success(message="报告编号比对正确")
                else:  
                    return ApiResponse.fail(message="报告编号比对有误，请仔细检查")
            elif ext == "docx":
                doc = Document(pdf_content)
                # 遍历每个节的页眉
                for section in doc.sections:
                    header = section.header
                    # 遍历页眉中的每个段落
                    for paragraph in header.paragraphs:
                        if report_code in paragraph.text or report_code.startswith("XLY"):
                            return ApiResponse.success(message="报告编号比对正确")
                return ApiResponse.fail(message="报告编号比对有误，请仔细检查")
        except:
            return ApiResponse.fail(message="报告编号获取有误，请仔细检查")



